#include <Windows.h>
#include <stdio.h>

enum PAGE_COLOR
{
	PG_COLOR_GREEN = 1, /* page may be released without high overhead */
	PG_COLOR_YELLOW, /* nice to have */
	PG_COLOR_RED	/* page is actively used */
};

union PageKey{
	struct {
    		CHAR	cColor: 8;
		UINT	cAddr: 24; 
		};
	UINT	uKey;
};

#define CALC_PAGE_KEY( Addr, Color )	(  (Color + Addr) << 8 )


struct PageDesc
{
	PageKey	uKey;
	PageDesc *next, *prev;
};

#define PAGE_INIT( Desc, Addr, Color )         do {                                               \
        (Desc).uKey = CALC_PAGE_KEY( Addr, Color ); 							\
     	(Desc).next = (Desc).prev = NULL;           						\
    	}											\
while(0)

static PageDesc* PageStrg[ 3 ];

void PageStrgInit(){
 PageStrg = (PageDesc*)malloc(3*sizeof(PageDesc) );
}


PageDesc* PageFind( void* ptr, char color){
  Pg = PageStrg[color];
  while(Pg) {
            if( Pg->uKey == CALC_PAGE_KEY(ptr,color) ) break;
           Pg = Pg -> next;}
           return Pg;
}

PageDesc* PageReclaim( UINT cnt ){
	UINT color = 0; 
	PageDesc* Pg = PageStrg[ color ];

	while( cnt  && color < 3){
		if( ! Pg){
			color++; 
			Pg = PageStrg[ color ];
		}
		
		Pg = Pg->next;
		PageRemove( PageStrg[ color ] );
		cnt--;
	
	}
}

PageDesc* PageInit( void* ptr, UINT color )
{
    PageDesc* pg = (PageDesc *)malloc(sizeof(PageDesc));
    if( !pg)  printf("Allocation has failed\n");
        return pg;
}

   PAGE_INIT(&pg, ptr, color); /
   return pg;
}

void PageDump()
{
	UINT color = 0;
	#define PG_COLOR_NAME(clr) #clr
	char* PgColorName[] =
	{
PG_COLOR_NAME(PG_COLOR_RED),
PG_COLOR_NAME(PG_COLOR_YELLOW_),
PG_COLOR_NAME(PG_COLOR_GREEN)	}; 

	while( color < PG_COLOR_RED )
	{
		printf("PgStrg[(%u) %c] ********** \n", color, PgColorName[color] );

		for( PageDesc* Pg = PageStrg[color++]; Pg ; Pg = Pg->next )
		{
		if( !(Pg->uAddr ) ) 
				continue;

			printf("Pg :Key = 0x%x, addr %p\n", Pg->uKey, Pg->uAddr );
		}
	}
	#undef PG_COLOR_NAME
}
